using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MQTTnet;
using MQTTnet.AspNetCore;
using MQTTnet.Protocol;
using MQTTnet.Server;

namespace Catastrophe.BasePC.UI
{
	public class Startup
	{
		private bool _useMqtt;

		private string _mqttUser = "";

		private string _mqttPwd = "";

		public static MqttServer MServer;

		public static Action<EventArgs> ActOnMqttServerStarted { get; set; }

		public static Action<ClientSubscribedTopicEventArgs> ActClientSubscribedTopicAsync { get; set; }

		public static Action<MqttApplicationMessageReceivedEventArgs> ActOnMqttServerApplicationMessageReceived { get; set; }

		public IConfiguration Configuration { get; }

		public Startup(IConfiguration configuration)
		{
			this.Configuration = configuration;
			this._mqttUser = this.Configuration.GetValue<string>("MqttUser");
			this._mqttPwd = this.Configuration.GetValue<string>("MqttPwd");
			this._useMqtt = configuration.GetValue<bool>("UseMqtt");
		}

		public void Configure(IApplicationBuilder app, IWebHostEnvironment environment)
		{
			app.UseRouting();
			if (this._useMqtt)
			{
				app.UseEndpoints(delegate(IEndpointRouteBuilder endpoints)
				{
					endpoints.MapConnectionHandler<MqttConnectionHandler>("/mqtt", delegate(HttpConnectionDispatcherOptions httpConnectionDispatcherOptions)
					{
						httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector = (IList<string> protocolList) => protocolList.FirstOrDefault() ?? string.Empty;
					});
				});
				app.UseMqttServer(delegate(MqttServer server)
				{
					Startup.MServer = server;
					server.ValidatingConnectionAsync += ValidateConnection;
					server.ClientConnectedAsync += OnClientConnected;
					server.ClientDisconnectedAsync += Server_ClientDisconnectedAsync;
					server.StartedAsync += Server_StartedAsync;
					server.StoppedAsync += Server_StoppedAsync;
					server.ClientSubscribedTopicAsync += Server_ClientSubscribedTopicAsync;
					server.ClientUnsubscribedTopicAsync += Server_ClientUnsubscribedTopicAsync;
				});
			}
			app.UseEndpoints(delegate(IEndpointRouteBuilder endpoints)
			{
				endpoints.MapControllers();
			});
		}

		public void ConfigureServices(IServiceCollection services)
		{
			if (this._useMqtt)
			{
				services.AddHostedMqttServer(delegate(MqttServerOptionsBuilder optionsBuilder)
				{
					optionsBuilder.WithDefaultEndpoint();
				});
				services.AddMqttConnectionHandler();
				services.AddConnections();
			}
			services.AddControllers().AddJsonOptions(delegate(JsonOptions cfg)
			{
				cfg.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
			});
			services.AddRouting();
		}

		public Task OnClientConnected(ClientConnectedEventArgs eventArgs)
		{
			Startup.MServer.InjectApplicationMessage(new InjectedMqttApplicationMessage(new MqttApplicationMessage
			{
				Topic = eventArgs.ClientId + ":ConnectState",
				Payload =new System.Buffers.ReadOnlySequence<byte>(new byte[1] { 1}),
				QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce
			})
			{
				SenderClientId = "server"
			});
			return Task.CompletedTask;
		}

		public Task ValidateConnection(ValidatingConnectionEventArgs eventArgs)
		{
			if (eventArgs.UserName != this._mqttUser || eventArgs.Password != this._mqttPwd)
			{
				eventArgs.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
			}
			else
			{
				eventArgs.ReasonCode = MqttConnectReasonCode.Success;
			}
			return Task.CompletedTask;
		}

		private Task Server_ClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs arg)
		{
			return Task.CompletedTask;
		}

		private Task Server_ClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs arg)
		{
			Startup.ActClientSubscribedTopicAsync?.Invoke(arg);
			return Task.CompletedTask;
		}

		private Task Server_ClientDisconnectedAsync(ClientDisconnectedEventArgs arg)
		{
			return Task.CompletedTask;
		}

		private Task Server_StartedAsync(EventArgs arg)
		{
			Startup.ActOnMqttServerStarted?.Invoke(arg);
			return Task.CompletedTask;
		}

		private Task Server_StoppedAsync(EventArgs arg)
		{
			return Task.CompletedTask;
		}
	}
}
